package com.sky.aspect;

import com.sky.annotation.LogOperation;
import com.sky.context.BaseContext;
import com.sky.entity.Log;
import com.sky.service.LogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;

@Slf4j
@Aspect
@Component
public class LogOperationAspect {
	@Autowired
	private LogService logService;

	// 从配置文件读取开关
	@Value("${sky.log-operation-enabled:true}") // 默认为 true
	private boolean logOperationEnabled;

	//环绕通知
	@Around("@annotation(logOperation)")
	public Object recordMethodTime(ProceedingJoinPoint pjp, LogOperation logOperation) throws Throwable {
		// 记录开始时间
		long startTime = System.currentTimeMillis();
		// 执行方法
		Object result = pjp.proceed();
		// 当前时间
		long endTime = System.currentTimeMillis();
		// 耗时
		long costTime = endTime - startTime;

		// 优先使用注解设置，否则使用全局配置
		boolean shouldLog = logOperation.enabled() && logOperationEnabled;

		if (shouldLog) {
			try {
				Log methodLog = new Log();
				methodLog.setOperateEmpId(BaseContext.getCurrentId());
				methodLog.setOperateTime(LocalDateTime.now());
				methodLog.setClassName(pjp.getTarget().getClass().getName());
				methodLog.setMethodName(pjp.getSignature().getName());
				methodLog.setMethodParams(Arrays.toString(pjp.getArgs()));

				// 注意：result 可能为 null，避免空指针
				methodLog.setMethodResult(result != null ? result.toString() : "null");
				methodLog.setCostTime(costTime);
				//打印某个类，某个方法，耗时，参数
				log.info(
						"类：{}，方法：{}，耗时：{}，参数：{}",
						methodLog.getClassName(),
						methodLog.getMethodName(),
						methodLog.getCostTime(),
						methodLog.getMethodParams()
				);
				logService.save(methodLog);
			} catch (Exception e) {
				log.error("记录操作日志失败: ", e);
				// 避免因日志异常影响主流程
			}
		}

		return result;
	}
}
